package com.xiaogao.aspect;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiaogao.common.annotation.SysLogOperateAnnotation;
import com.xiaogao.common.utils.ip.IpUtils;
import com.xiaogao.common.utils.token.JwtUtils;
import com.xiaogao.sys.model.SysLogOperate;
import com.xiaogao.sys.service.SysLogOperateService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
@RequiredArgsConstructor
public class SysLogOperateAspect {
    private final SysLogOperateService operateService;
    private final HttpServletRequest servletRequest;

    @Around("@annotation(com.xiaogao.common.annotation.SysLogOperateAnnotation)")
    public Object logBefore(ProceedingJoinPoint joinPoint) {
        // 1、构建SysLogOperate入库对象
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        SysLogOperateAnnotation sysLogOperateAnnotation = signature.getMethod().getAnnotation(SysLogOperateAnnotation.class);
        String operateType = sysLogOperateAnnotation.value();
        String host = IpUtils.getClientIp();
        String url = servletRequest.getRequestURI();
        String requestType = servletRequest.getMethod();
        String ownerId = JwtUtils.userId(servletRequest.getHeader("token"));
        Object[] args = joinPoint.getArgs();
        String params = parseParams(args);
        LocalDateTime startTime = LocalDateTime.now();
        SysLogOperate sysLogOperate = SysLogOperate.builder().operateType(operateType).host(host).url(url).requestType(requestType).ownerId(ownerId).params(params).startTime(startTime).build();
        try {
            // 2、执行方法
            Object result = joinPoint.proceed();
            // 记录成功状态和耗时
            sysLogOperate.setStatus("0");
            sysLogOperate.setEndTime(LocalDateTime.now());
            // 3、入库
            operateService.save(sysLogOperate);
            return result;
        } catch (Throwable e) {
            // 6、记录失败状态、耗时和异常信息
            sysLogOperate.setStatus("1");
            sysLogOperate.setEndTime(LocalDateTime.now());
            sysLogOperate.setMessage(e.getMessage());
            // 7、入库
            operateService.save(sysLogOperate);
            throw new RuntimeException(e); // 重新抛出异常
        }
    }

    private String parseParams(Object[] args) {
        try {
            Map<String, Object> params = new HashMap<>();
            for (int i = 0; i < args.length; i++) {
                params.put("arg" + i, args[i]);
            }
            return new ObjectMapper().writeValueAsString(params);
        } catch (JsonProcessingException e) {
            return "参数序列化失败";
        }
    }
}

